<?php
final class Front implements interface_front {
    protected $registry;

    public function __construct($dir_system) {

        // Registry
        $registry = new Registry();

        // Loader
        $loader = new Loader($registry);

        // Engine Auto Loading
        $loader->set_status(true)
            ->add_path($dir_system . 'interface/')
            ->add_path($dir_system . 'abstract/')
            ->add_path($dir_system . 'class/');

        $loader->set_path('dir_system', $dir_system);

        // Error Handling
        $error = new error();
        set_exception_handler(array($error, 'handleException'));
        set_error_handler(array($error, 'handleError'));
        register_shutdown_function(array($error, 'handleShutdown'));

        // System Config
        $cfg_system = new Config($dir_system . 'config/system.ini');
        if($cfg_system->parse()){
        
            // Setup System Paths 
            $cfg_system->set_section('paths');
            $loader->set_paths($cfg_system->get_all());

            // Error Settings
            $cfg_system->set_section('system'); 
            $error->setDisplay($cfg_system->get('error_display'));

            // Error Log
            if($cfg_system->get('error_log')){

                $log_path = $loader->get_path('dir_logs'); 
                $error_file = $log_path . $cfg_system->get('error_filename');

                if (!is_writable($log_path)) {
			        exit('Error: Logs directory needs to be writable !');
		        }

                $error->setFilename($error_file);
            }
            $error->setLog($cfg_system->get('error_log'));

            $registry->set('cfg_system', $cfg_system);
        }
        unset($cfg_system);

        $registry->set('load', $loader);
        $registry->set('error_handler', $error);
        $this->registry = $registry;
    }
    
    public function __get($key) {
       return $this->registry->get($key);
    }

    public function __set($key, $value) {
        $this->registry->set($key, $value);
    }
   
    public function get($key) {
       return $this->registry->get($key);
    }

    public function set($key, $value) {
        $this->registry->set($key, $value);
    }
    public function config($app) {
        return $this->load->config($app);
    }
    public function bootstrap(interface_config $config) {
        
        $config->parse();

        $config->set_section('app');
        $filename = $config->get('filename');
        $classname = $config->get('classname');
        $bootstrap = $config->get('bootstrap');
        $app_path = $config->set_section('paths')->get('dir_app');

        $bootstrap = $app_path . $bootstrap;
        include_once($bootstrap);
        $boot = new bootstrap($this->registry);
        $boot->bootstrap();
        unset($boot);

        $filename = $app_path . $filename;
        include_once($filename);

        return new $classname($this->registry, $config);
    }

    public function dispatch(interface_app $app) {

        $app->pre_dispatch();

        $action     = $app->get_action();
        $pre_action = $app->get_pre_action();

        foreach ($pre_action as $pre_action) {
            $result = $app->controller($pre_action, true);

            if ($result instanceof interface_action) {
                $action = $result;
                break;
            }
        }
        
        while ($action instanceof interface_action) {
            $action = $app->controller($action, true);
        }
        return $this->response->output();
    }
}
?>
